// 实现这个项目的构建任务
const { src, dest, parallel, series, watch } = require("gulp");

const loadPlugins = require("gulp-load-plugins");
const plugins = loadPlugins();
const browserSync = require("browser-sync");
const del = require("del");

// 创建一个开发服务器
const bs = browserSync.create();

// 清除dist
const clean = () => {
  return del(["dist"]);
};
// gulp 样式编译
const style = () => {
  return (
    //   有一种情况当Dist写入后，并没有保存之前的目录，这种情况
    // 可以加一个base:"src" 会默认保存 src往后的路径 assets/styles/
    src("src/assets/styles/*.scss", { base: "src" })
      // 操作流 转换sass css
      .pipe(
        plugins.sass({
          outputStyle: "expanded",
        })
      )
      //   操作流程，写入文件到
      .pipe(dest("dist"))
      .pipe(bs.reload({ stream: true }))
  );
};

// script脚本编辑
const script = () => {
  return src("src/assets/scripts/*.js", { base: "src" })
    .pipe(
      plugins.babel({
        presets: ["@babel/preset-env"],
      })
    )
    .pipe(dest("dist"))
    .pipe(bs.reload({ stream: true }));
};
const data = {
  menus: [
    {
      name: "Home",
      icon: "aperture",
      link: "index.html",
    },
    {
      name: "Features",
      link: "features.html",
    },
    {
      name: "About",
      link: "about.html",
    },
    {
      name: "Contact",
      link: "#",
      children: [
        {
          name: "Twitter",
          link: "https://twitter.com/w_zce",
        },
        {
          name: "About",
          link: "https://weibo.com/zceme",
        },
        {
          name: "divider",
        },
        {
          name: "About",
          link: "https://github.com/zce",
        },
      ],
    },
  ],
  pkg: require("./package.json"),
  date: new Date(),
};
// 模板编译
const page = () => {
  return src("src/**/*.html", { base: "src" })
    .pipe(plugins.swig({ data, defaults: { cache: false } })) // 防止模板缓存导致页面不能及时更新
    .pipe(dest("dist"))
    .pipe(bs.reload({ stream: true }));
};
// 图片压缩
const image = () => {
  return src("src/assets/images/**", { base: "src" })
    .pipe(plugins.imagemin())
    .pipe(dest("dist"));
};

// 字体文件处理 有svj的原因可以使用 imagemin做处理，剩下的字体单纯copy到dist内即可
const font = () => {
  return src("src/assets/fonts/**", { base: "src" })
    .pipe(plugins.imagemin())
    .pipe(dest("dist"));
};

// 其他文件拷贝
const extra = () => {
  return src("public/**", { base: "public" }).pipe(dest("dist"));
};

// useref文件构建引入
const useref = () => {
  return (
    src("dist/*.html", { base: "dist" })
      .pipe(plugins.useref({ searchPath: ["dist", "."] }))
      // html js css 压缩
      .pipe(plugins.if(/\.js$/, plugins.uglify()))
      .pipe(plugins.if(/\.css$/, plugins.cleanCss()))
      .pipe(plugins.if(/\.html$/, plugins.htmlmin({
        collapseWhitespace:true,
        minifyCSS:true,
        minifyJS:true
      })))
      // 因为读写冲突的原因，临时放到release目录只是单纯测试
      .pipe(dest("release"))
  );
};
const compile = parallel(style, script, page);
// extra 并没有对src做构建处理，我们可以再把compile 与 extra从新组合
// series与 parallel的差距就是 series是一个前后执行的方法，必须执行前一个方法，才会执行
// 后续方法，不是同步执行的
const build = series(clean, parallel(compile, image, font, extra));

// 启动热更新服务器browserSync
const server = () => {
  // 监测文件目录下的文件被修改时
  watch("src/assets/styles/*.scss", style);
  watch("src/assets/scripts/*.js", script);
  watch("src/**/*.html", page);
  // image 与 font publick 在测试环境中不需要实时的构建，只有在Bulid中再执行构建
  // 我们可以在browser-sync中设置basedir中来让他通过SRC与publick加载需要的图片与静态文件

  // 但是如果我们有替换图片的需求可以做如下处理自动更新浏览器
  watch(
    ["src/assets/styles/*.scss", "src/assets/scripts/*.js", "src/**/*.html"],
    bs.reload
  );
  // watch("src/assets/images/**", image);
  // watch("src/assets/fonts/**", font);
  // watch("public/**", extra);

  bs.init({
    notify: false,
    port: 2003,
    // files: "dist/**",
    server: {
      baseDir: ["dist", "src", "public"],
      routes: {
        "/node_modules": "node_modules",
      },
    },
  });
};

const develop = series(compile, server);
// 接下来build前我们把dist目录清除掉
module.exports = {
    clean,serve,build,
};
